Virtual machine architecture has evolved over the years to include different input/output (IO) paths to the IO hardware of the physical computer system. For example, a hypervisor can include an emulated IO path. An IO controller emulator, e.g., a software model of a hardware device, one which responds enough like the hardware device that the device driver for the driver functions normally, can execute in a hypervisor and a driver for the IO controller can run in a virtual machine. In this architecture the IO controller emulator runs from a centralized location and is used to service all virtual machines. This architecture was chosen because it reduces the memory footprint of each virtual machine and provides a way to update one emulator and update all emulators in the system.
An emulator in the hypervisor can be run when a driver touches resources, e.g., memory mapped to the controller or ports of the controller and the hypervisor can trap the request. The hypervisor can suspend a virtual processor running the driver and pass control to the IO controller emulator along with the value written by the driver. The IO emulator can execute and determine what operation the driver issued and perform the operation on behalf of the driver.
This architecture, however, is computationally expensive because it requires a context switch for each byte written an IO register or to memory mapped IO space, and it may require hundreds of writes to hundreds of registers before an IO request is completed. In addition to being computationally expensive, since the emulator executes within the hypervisor, it presents a large attack surface that could be potentially exploited in order to gain control of the physical computer system. For example, emulators are emulating complex hardware state machines and for a software developer it is relatively difficult to ensure that each emulator works for every possible combination of states that the emulator could be put in. A user could potentially generate a stream of illegal operations that cause the hypervisor to, for example, allow a user to access memory outside of the virtual machine or crash the hypervisor.
Virtualized systems also include another IO path that is easier to analyze from a security point of view and requires fewer processor cycles to run because it does not emulate IO devices. In this path a paravirtualization driver, e.g., a driver that was specifically designed to operate in a virtualized environment, can use high level communication protocols such as SCSI to send IO requests to a virtualization service provider that can parse the protocol and execute the IO job on its behalf. This path is more secure because it presents a smaller attack surface and security protocols can be used to determine what traffic is sent. This path is not always available though. For example, this path could be unavailable because a paravirtualization driver has not been created for the IO device or a user has not installed it. This path also typically relies on services offered by the guest operating system and may not be available during boot. Thus, the emulation path can not be simply eliminated because there are instances where it may be required.
Accordingly, virtual machine architecture has evolved to the point where there are two paths for doing the same thing. One is computationally expensive and presents a large attack surface; the other is computationally much cheaper and presents a smaller attack surface. Since the emulation path can not be simply eliminated, techniques for making it less computationally expensive, more secure, and more similar to the paravirtualization path are desirable.